﻿using OneOfAll.Common.Bussiness;
using OneOfAll.Common.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace OneOfAll.UserControls
{
    /// <summary>
    /// BaseObjectControl.xaml 的交互逻辑
    /// </summary>
    public partial class MonsterControl : UserControl
    {


        public MonsterModel Info
        {
            get { return (MonsterModel)GetValue(InfoProperty); }
            set { SetValue(InfoProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Info.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InfoProperty =
            DependencyProperty.Register("Info", typeof(MonsterModel), typeof(MonsterControl), new PropertyMetadata(null));



        public double X
        {
            get { return (double)GetValue(XProperty); }
            set { SetValue(XProperty, value); }
        }

        // Using a DependencyProperty as the backing store for X.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty XProperty =
            DependencyProperty.Register("X", typeof(double), typeof(MonsterControl), new PropertyMetadata(0.0, (sender, e) =>
            {
                var dp = sender as MonsterControl;
                if (dp == null) return;
                dp.XChanged();
            }));



        public double Y
        {
            get { return (double)GetValue(YProperty); }
            set { SetValue(YProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Y.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty YProperty =
            DependencyProperty.Register("Y", typeof(double), typeof(MonsterControl), new PropertyMetadata(0.0, (sender, e) =>
            {
                var dp = sender as MonsterControl;
                if (dp == null) return;
                dp.YChanged();
            }));

        Storyboard storyboard;

        private void XChanged()
        {
            if (Info != null)
                Info.X = X;
        }

        private void YChanged()
        {
            if (Info != null)
                Info.Y = Y;
        }

        public void Start()
        {
            ExcuteBehavior();
        }

        internal void ExcuteBehavior()
        {
            ScreenHelper.Instance.GetMonsterStatus(Info.ScreenName, Info);
            List<DoubleAnimationBase> animations;
            switch (Info.Status)
            {
                case ObjectStatusEnum.空闲:
                    animations = GetStandAnimation();
                    break;
                case ObjectStatusEnum.巡逻:
                    animations = GetPatrolBehavior();
                    break;
                case ObjectStatusEnum.追击:
                    animations = GetFollowBehavior();
                    break;
                case ObjectStatusEnum.死亡:
                    animations = GetDeadBehavior();
                    break;
                case ObjectStatusEnum.攻击:
                    animations = GetAttachBehavior();
                    break;
                default:
                    animations = GetStandAnimation();
                    break;
            }
            storyboard = new Storyboard();
            foreach (var animation in animations)
            {
                animation.Completed += Animation_Completed;
                storyboard.Children.Add(animation);
            }
            storyboard.Begin();
        }

        private List<DoubleAnimationBase> GetAttachBehavior()
        {
            DoubleAnimation deadAnimation = new DoubleAnimation()
            {
                From = 1,
                To = 0,
                AutoReverse = true,
                Duration = new Duration(new TimeSpan(0, 0, 0, 0, Global.GlobalResource.GameSpeed / 2))
            };
            Storyboard.SetTarget(deadAnimation, this);
            Storyboard.SetTargetProperty(deadAnimation, new PropertyPath("Opacity"));
            return new List<DoubleAnimationBase>() { deadAnimation };
        }

        private void Animation_Completed(object sender, EventArgs e)
        {
            switch (Info.Status)
            {
                case ObjectStatusEnum.死亡:
                    Info.IsDispose = true;
                    break;
                default:
                    ExcuteBehavior();
                    break;
            }
        }

        private List<DoubleAnimationBase> GetDeadBehavior()
        {
            DoubleAnimation deadAnimation = new DoubleAnimation()
            {
                From = 1,
                To = 0,
                Duration = new Duration(new TimeSpan(0, 0, Global.GlobalResource.GameSpeed * 2))
            };
            Storyboard.SetTarget(deadAnimation, this);
            Storyboard.SetTargetProperty(deadAnimation, new PropertyPath("Opacity"));
            return new List<DoubleAnimationBase>() { deadAnimation };
        }

        private List<DoubleAnimationBase> GetFollowBehavior()
        {
            List<Point> path = ScreenHelper.Instance.GetFollowPath(Info.ScreenName, Info);
            if (path == null || path.Count == 0)
                return GetStandAnimation();

            return GetMoveAnimation(path);
        }

        private List<DoubleAnimationBase> GetPatrolBehavior()
        {
            List<Point> path = ScreenHelper.Instance.GetPatrolPath(Info.ScreenName, Info);
            if (path == null || path.Count == 0)
                return GetStandAnimation();

            return GetMoveAnimation(path);
        }

        private List<DoubleAnimationBase> GetMoveAnimation(List<Point> path)
        {
            if (path == null || path.Count == 0)
                return GetStandAnimation();

            List<DoubleAnimationBase> animations = new List<DoubleAnimationBase>();
            //创建故事板
            int cost = Global.GlobalResource.GameSpeed / path.Count;
            DoubleAnimationUsingKeyFrames keyFramesAnimationX = new DoubleAnimationUsingKeyFrames();
            keyFramesAnimationX.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));
            Storyboard.SetTarget(keyFramesAnimationX, this);
            Storyboard.SetTargetProperty(keyFramesAnimationX, new PropertyPath("X"));
            DoubleAnimationUsingKeyFrames keyFramesAnimationY = new DoubleAnimationUsingKeyFrames();
            keyFramesAnimationY.Duration = new Duration(TimeSpan.FromMilliseconds(path.Count * cost));
            Storyboard.SetTarget(keyFramesAnimationY, this);
            Storyboard.SetTargetProperty(keyFramesAnimationY, new PropertyPath("Y"));
            for (int i = 0; i <= path.Count(); i++)
            {
                //加入X轴方向的匀速关键帧
                LinearDoubleKeyFrame keyFrame = new LinearDoubleKeyFrame();
                keyFrame.Value = i == 0 ? Info.X : path[i - 1].X;
                keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));
                keyFramesAnimationX.KeyFrames.Add(keyFrame);
                keyFrame = new LinearDoubleKeyFrame();
                keyFrame.Value = i == 0 ? Info.Y : path[i - 1].Y;
                keyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(cost * i));
                keyFramesAnimationY.KeyFrames.Add(keyFrame);
            }
            animations.Add(keyFramesAnimationX);
            animations.Add(keyFramesAnimationY);

            return animations;
        }

        private List<DoubleAnimationBase> GetStandAnimation()
        {
            DoubleAnimation idleAnimation = new DoubleAnimation()
            {
                From = Info.Y,
                To = Info.Y + Global.GlobalResource.GridSize / 2,
                AutoReverse = true,
                Duration = new Duration(new TimeSpan(0, 0, 0, 0, Global.GlobalResource.GameSpeed / 2))
            };
            Storyboard.SetTarget(idleAnimation, this);
            Storyboard.SetTargetProperty(idleAnimation, new PropertyPath("Y"));
            return new List<DoubleAnimationBase>() { idleAnimation };
        }


        public MonsterControl()
        {
            InitializeComponent();
        }


    }
}
